unit product;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls, Buttons, Spin, EditBtn,
  clientdb, db;

type

  { TProductForm }

  TProductForm = class ( TForm )
    SuppliersRefEdit: TLabeledEdit;
    DiscountComboBox: TComboBox;
    DeptCombo: TComboBox;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    RetailBox: TCalcEdit;
    NewCodeButton: TButton;
    VATButton: TButton;
    ButtonPanel: TPanel;
    CancelButton: TBitBtn;
    BarcodeEdit: TEdit;
    InitCountLabel: TLabel;
    Discontinued: TCheckBox;
    Label1: TLabel;
    BarcodeLabel: TLabel;
    InitCount: TSpinEdit;
    SupplierBox: TComboBox;
    NameBox: TLabeledEdit;
    CostBox: TLabeledEdit;
    OKButton: TBitBtn;
    MainPanel: TPanel;
    NewSupplierButton: TButton;
    procedure CostBoxExit ( Sender: TObject ) ;
    procedure FormCreate ( Sender: TObject ) ;
    procedure NewCodeButtonClick(Sender: TObject);
    procedure NewSupplierButtonClick(Sender: TObject);
    procedure OKButtonClick(Sender: TObject);
    procedure RetailBoxExit(Sender: TObject);
    procedure VATButtonClick(Sender: TObject);
    procedure GetDepartments;
    procedure GetDiscounts;
  private
    { private declarations }
    CurrentProduct: integer;
    FErrorMessage: string;
    FOnError: TDBErrorEvent;
    function ValidateInput: Boolean;
  public
    { public declarations }
    procedure RefreshSuppliers;
    function ShowNew: TModalResult;
    function ShowEdit(barcode: string) : TModalResult;
    property OnError: TDBErrorEvent read FOnError write FOnError;
    property ErrorMessage: string read FErrorMessage;
  end;


const
  TEMP_SYSTEM_CONFIG = '/home/curator/tmp/Pascal/firepos/Server/system.dat';

implementation

uses fpstructs, fposUtils, main;

{ TProductForm }

procedure TProductForm.FormCreate ( Sender: TObject ) ;
begin
  RefreshSuppliers;
  GetDepartments;
  GetDiscounts;
  SupplierBox.ItemIndex := -1;
end;

procedure TProductForm.NewCodeButtonClick(Sender: TObject);
var
  r: integer;
  teststr: String;
  test2: String;
begin
  r := 1;
  try
    MainDB.SQL := 'SELECT barcode FROM products'
                             + ' WHERE barcode LIKE ''11%'''
                             + ' ORDER BY barcode';
    MainDB.Open;
    teststr := '110001';
    while not MainDB.EOF do
      begin
//        test2 :=DB.Fields[0].AsString;
        if MainDB.Fields[0].AsString = teststr then MainDB.Next
        else exit;
        Inc(r);
        teststr := FormatNumber('11', r, 4);
      end;
  finally
    BarcodeEdit.Text := teststr;
    MainDB.Close;
  end;
end;

procedure TProductForm.NewSupplierButtonClick(Sender: TObject);
var
  newsupplier: String;
begin
 { SupplierForm := TSupplierForm.Create(Self);
  SupplierForm.Caption := 'New Supplier';
  if SupplierForm.ShowNew = mrOk then
    begin
      if not MainDB.ExecRemoteSQL( 'INSERT INTO suppliers '
                 + ' (name, address, postcode, telephone, email) '
                 + 'VALUES(''' + EscapeQuotes( SupplierForm.SupplierName.Text )
                 + ''',''' + EscapeQuotes( SupplierForm.AddressMemo.Text )
                 + ''',''' + SupplierForm.PostCode.Text
                 + ''',''' + SupplierForm.Telephone.Text
                 + ''',''' + SupplierForm.Email.Text
                 + ''' );')
         then
           begin
             FErrorMessage := 'Error when adding new product';
             if Assigned(FOnError) then FOnError(FErrorMessage);
           end;
      RefreshSuppliers;
      SupplierBox.ItemIndex := SupplierBox.Items.IndexOf(SupplierForm.SupplierName.Text);
    end;
  SupplierForm.Free; }
  if MainForm.NewSupplier(newsupplier) then
    begin
      SupplierBox.ItemIndex := SupplierBox.Items.IndexOf(newsupplier);
      RefreshSuppliers;
    end;
end;

procedure TProductForm.OKButtonClick(Sender: TObject);
begin
  if ValidateInput then ModalResult := mrOK;
end;

procedure TProductForm.RetailBoxExit(Sender: TObject);
var
  c: Extended;
begin
  if Length(RetailBox.Text) > 0 then
    begin
      if TryStrToFloat(RetailBox.Text, c)
         then RetailBox.Text := FormatFloat('0.00', c)
      else
        begin
        ShowMessage('Invalid Amount');
        RetailBox.SetFocus;
        end;
    end;
end;

procedure TProductForm.VATButtonClick(Sender: TObject);
var
  f: Extended;
begin
  if TryStrToFloat(CostBox.Text, f)
     then CostBox.Text := FormatFloat('0.00', f*(1+VAT_RATE));
end;

procedure TProductForm.GetDepartments;
var
  r: integer;
begin
  r := 1;
  try
    MainDB.SQL := 'SELECT id, name FROM Departments ORDER BY name';
    MainDB.Open;
    MainDB.First;
    if MainDB.State=dsBrowse then
        while not MainDB.EOF do
          begin
            DeptCombo.Items.AddObject(MainDB.FieldByName('name').AsString,
                                   TObject(MainDB.FieldByName('id').AsInteger));
            MainDB.Next;
          end;
  finally
    MainDB.Close;
  end;
end;

procedure TProductForm.GetDiscounts;
var
    r: integer;
  begin
    r := 1;
    try
      MainDB.SQL := 'SELECT discountID, description FROM Discounts ORDER BY description';
      MainDB.Open;
      MainDB.First;
      if MainDB.State=dsBrowse then
          while not MainDB.EOF do
            begin
              DiscountComboBox.Items.AddObject(MainDB.FieldByName('description').AsString,
                                     TObject(MainDB.FieldByName('discountID').AsInteger));
              MainDB.Next;
            end;
    finally
      MainDB.Close;
    end;
end;

function TProductForm.ValidateInput: Boolean;
begin
  Result := false;
  NameBox.Text := Trim(NameBox.Text);
  if Length(NameBox.Text) < 3 then
     begin
       ShowMessage('Product name must be at least 3 characters in length');
       NameBox.SetFocus;
       exit;
     end
  else if Length(BarcodeEdit.Text) < 6 then
     begin
       ShowMessage('Invalid barcode');
       BarcodeEdit.SetFocus;
       exit;
     end
  else if SupplierBox.ItemIndex < 0 then
     begin
       ShowMessage('Select a valid supplier');
       SupplierBox.SetFocus;
       exit;
     end
  else if DeptCombo.ItemIndex < 0 then
     begin
       ShowMessage('Select a valid sales department');
       DeptCombo.SetFocus;
       exit;
     end
  else if not IsValidCost(CostBox.Text) then
     begin
       ShowMessage('Enter a valid cost price');
       CostBox.SetFocus;
       exit;
     end
  else if not IsValidCost(RetailBox.Text) then
     begin
       ShowMessage('Enter a valid retail price');
       RetailBox.SetFocus;
       exit;
     end
  else if InitCount.Value < 0 then
     begin
       ShowMessage('Initial stock must be 0 or greater');
       InitCount.SetFocus;
       exit;
     end
  else Result := true;
end;

procedure TProductForm.CostBoxExit ( Sender: TObject ) ;
var
  c: Extended;
begin
  if Length(RetailBox.Text)=0 then
    if Length(CostBox.Text) > 0 then
      begin
        if TryStrToFloat(CostBox.Text, c) then
          begin
            CostBox.Text := FormatFloat('0.00',c);
            if RetailBox.AsInteger=0
               then RetailBox.Text := FormatFloat('0.00', c * MARKUP);
          end
        else
          begin
            ShowMessage('Invalid Amount');
            CostBox.SetFocus;
          end;
    end;
end;


procedure TProductForm.RefreshSuppliers;
var
  r: integer;
begin
  r := 1;
  try
    MainDB.SQL := 'SELECT id, name FROM suppliers ORDER BY name';
    MainDB.Open;
    SupplierBox.Clear;
    while not MainDB.EOF do
      begin
        SupplierBox.Items.AddObject(MainDB.FieldByName('name').AsString,
                               TObject(MainDB.FieldByName('id').AsInteger));
        MainDB.Next;
      end;
  finally
    MainDB.Close;
  end;
end;

function TProductForm.ShowNew: TModalResult;
var
  discontinuedflag: char;
begin
  Result := ShowModal;
  if Result = mrOK then
     try
       if Discontinued.Checked
          then discontinuedflag := '1'
          else discontinuedflag := '0';
       if not MainDB.ExecRemoteSQL( 'INSERT INTO Products '
                  + '(barcode,name,suppliersref,suppliercode,costprice,saleprice,dept,stocklevel,discontinued) '
                  + 'VALUES(''' +  BarcodeEdit.Text
                  + ''',''' + EscapeQuotes( NameBox.Text )
                  + ''',''' + SuppliersRefEdit.Text
                  + ''',' + IntToStr(Integer(SupplierBox.Items.Objects[SupplierBox.ItemIndex]))
                  + ',' + CostBox.Text
                  + ',' + RetailBox.Text
                  + ',' + IntToStr(Integer(DeptCombo.Items.Objects[DeptCombo.ItemIndex]))
                  + ',' + InitCount.Text
                  + ',' + discontinuedflag
                  + ' );', True)
          then
            begin
              FErrorMessage := 'Error when adding new product';
              if Assigned(FOnError) then FOnError(FErrorMessage);
              Result := mrCancel;
            end;

     finally
       MainDB.Close;
     end;

end;

function TProductForm.ShowEdit(barcode: string): TModalResult;
var
  query: String;
  discount: Integer;
  x: Integer;
  discontinuedflag: Char;
begin
  try
    query := 'SELECT productid, products.name AS name, suppliers.name AS supplier, costprice, saleprice, discount, Departments.name AS dept, suppliersref, discontinued '
           + 'FROM products, suppliers, departments WHERE products.barcode=''' + barcode +''' AND suppliers.id=products.suppliercode '
           + 'AND Departments.id=products.dept;';
    {$IFDEF DEBUG} writeln(query); {$ENDIF}
    MainDB.SQL := query;
    MainDB.Open;
      begin
        CurrentProduct := MainDB.FieldByName('productid').AsInteger;
        BarcodeEdit.Text := barcode;
        SuppliersRefEdit.Text := MainDB.FieldByName('suppliersref').AsString;
        NameBox.Text := MainDB.FieldByName('name').AsString;
        SupplierBox.ItemIndex := SupplierBox.Items.IndexOf( MainDB.FieldByName('supplier').AsString );
        CostBox.Text := FormatFloat('0.00', MainDB.FieldByName('costprice').AsFloat);
        RetailBox.Text := FormatFloat('0.00', MainDB.FieldByName('saleprice').AsFloat);
        DeptCombo.ItemIndex := DeptCombo.Items.IndexOf( MainDB.FieldByName('dept').AsString);
        discount := MainDB.FieldByName('discount').AsInteger;
        if discount>0 then
          for x := 1 to DiscountComboBox.Items.Count-1 do
              if Integer(DiscountComboBox.Items.Objects[x])=discount
                 then DiscountComboBox.ItemIndex := x;
        Discontinued.Checked := MainDB.FieldByName('discontinued').AsInteger<>0;
        InitCount.Enabled := false;
      end;
   Result := ShowModal;
   if Result = mrOk then
      begin
        if Discontinued.Checked
           then discontinuedflag := '1'
           else discontinuedflag := '0';
        discount := 0;
        if DiscountComboBox.ItemIndex>0
           then discount := Integer(DiscountComboBox.Items.Objects[DiscountComboBox.ItemIndex]);
        query := 'UPDATE products SET '
                 + 'barcode=''' + BarcodeEdit.Text
                 + ''', suppliersref=''' + SuppliersRefEdit.Text
                 + ''', name=''' + EscapeQuotes( NameBox.Text )
                 + ''', suppliercode=' + IntToStr(Integer(SupplierBox.Items.Objects[SupplierBox.ItemIndex]))
                 + ', costprice=' + CostBox.Text
                 + ', saleprice=' + RetailBox.Text
                 + ', dept=' + IntToStr(Integer(DeptCombo.Items.Objects[DeptCombo.ItemIndex]))
                 + ', discount=' + IntToStr(discount)
                 + ', discontinued=' + discontinuedflag
                 + ' WHERE productid=' + IntToStr(CurrentProduct) + ';';
        if not MainDB.ExecRemoteSQL( query, true) then
          begin
            {$IFDEF DEBUG} writeln('Error modifying product'); {$ENDIF}
            FErrorMessage := 'Error modifying product';
            if Assigned(FOnError) then FOnError(FErrorMessage);
            Result := mrCancel;
          end;
      end;
  finally
   MainDB.Close;
 end;
end ;

initialization
  {$I product.lrs}

end.

